home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DKBSRC.ARJ / TEXTURE.C < prev    next >
C/C++ Source or Header  |  1991-05-04  |  36KB  |  1,246 lines

  1. /*****************************************************************************
  2. *
  3. *                                   texture.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements solid texturing functions such as wood, marble, and
  8. *  bozo.  The noise function used here is the one described by Ken Perlin in
  9. *  "Hypertexture", SIGGRAPH '89 Conference Proceedings page 253.
  10. *
  11. * This software is freely distributable. The source and/or object code may be
  12. * copied or uploaded to communications services so long as this notice remains
  13. * at the top of each file.  If any changes are made to the program, you must
  14. * clearly indicate in the documentation and in the programs startup message
  15. * who it was who made the changes. The documentation should also describe what
  16. * those changes were. This software may not be included in whole or in
  17. * part into any commercial package without the express written consent of the
  18. * author.  It may, however, be included in other public domain or freely
  19. * distributed software so long as the proper credit for the software is given.
  20. *
  21. * This software is provided as is without any guarantees or warranty. Although
  22. * the author has attempted to find and correct any bugs in the software, he
  23. * is not responsible for any damage caused by the use of the software.  The
  24. * author is under no obligation to provide service, corrections, or upgrades
  25. * to this package.
  26. *
  27. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  28. * about them.  Also, if you have any comments or questions, you may contact me
  29. * at the following address:
  30. *
  31. *     David Buck
  32. *     22C Sonnet Cres.
  33. *     Nepean Ontario
  34. *     Canada, K2H 8W7
  35. *
  36. *  I can also be reached on the following bulleton boards:
  37. *
  38. *     OMX              (613) 731-3419
  39. *     Mystic           (613) 596-4249  or  (613) 596-4772
  40. *
  41. *  Fidonet:   1:163/109.9
  42. *  Internet:  dbuck@ccs.carleton.ca
  43. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     The "You Can Call Me RAY" BBS (708) 358-5611
  48. *     The Information Exchange BBS  (708) 945-5575
  49. *
  50. *
  51. *  The Noise and DNoise functions (and associated functions) were written by
  52. *  Robert Skinner (robert@sgi.com) and are used here with his permission.
  53. *  They are a lot better than the noise functions I had before!
  54. *
  55. *****************************************************************************/
  56.  
  57.  
  58. #include "frame.h"
  59. #include "vector.h"
  60. #include "dkbproto.h"
  61.  
  62. extern long Calls_To_Noise, Calls_To_DNoise;
  63.  
  64. #define MINX    -10000        /* Ridiculously large scaling values */
  65. #define MINY    MINX
  66. #define MINZ    MINX
  67.  
  68. #define MAXSIZE 267
  69. #define RNDMASK 0x7FFF
  70. #define RNDDIVISOR (float) RNDMASK
  71. #define NUMBER_OF_WAVES 10
  72. #define SINTABSIZE 1000
  73.  
  74. #define FLOOR(x) ((x) >= 0.0 ? floor(x) : (0.0 - floor(0.0 - (x)) - 1.0))
  75. #define FABS(x) ((x) < 0.0 ? (0.0 - x) : (x))
  76. #define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
  77. #define REALSCALE ( 2.0 / 65535.0 )
  78. #define Hash3d(a,b,c) hashTable[(int)(hashTable[(int)(hashTable[(int)((a) & 0xfffL)] ^ ((b) & 0xfffL))] ^ ((c) & 0xfffL))]
  79. #define INCRSUM(m,s,x,y,z)    ((s)*(RTable[m]*0.5        \
  80.                     + RTable[m+1]*(x)    \
  81.                     + RTable[m+2]*(y)    \
  82.                     + RTable[m+3]*(z)))
  83.  
  84. extern int Options;
  85.  
  86. DBL sintab [SINTABSIZE];
  87. DBL frequency[NUMBER_OF_WAVES];
  88. VECTOR Wave_Sources[NUMBER_OF_WAVES];
  89. DBL    RTable[MAXSIZE];
  90. short *hashTable;
  91. unsigned short crctab[256] =
  92. {
  93.    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  94.    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  95.    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  96.    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  97.    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  98.    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  99.    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  100.    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  101.    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  102.    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  103.    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  104.    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  105.    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  106.    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  107.    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  108.    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  109.    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  110.    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  111.    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  112.    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  113.    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  114.    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  115.    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  116.    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  117.    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  118.    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  119.    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  120.    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  121.    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  122.    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  123.    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  124.    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  125. };
  126.  
  127.  
  128. void Compute_Colour (Colour, Colour_Map, value)
  129.    COLOUR *Colour;
  130.    COLOUR_MAP *Colour_Map;
  131.    DBL value;
  132.    {
  133.    register int i;
  134.    COLOUR_MAP_ENTRY *Entry;
  135.    register DBL fraction;
  136.  
  137.    if (value > 1.0)
  138.       value = 1.0;
  139.  
  140.    if (value < 0.0)
  141.       value = 0.0;
  142.  
  143.    for (i = 0, Entry = &(Colour_Map->Colour_Map_Entries[0]) ; i < Colour_Map -> Number_Of_Entries ; i++, Entry++)
  144.       if ((value >= Entry->start) && (value <= Entry->end))
  145.       {
  146.       fraction = (value - Entry->start) / (Entry->end - Entry->start);
  147.       Colour -> Red = Entry->Start_Colour.Red + fraction * (Entry->End_Colour.Red - Entry->Start_Colour.Red);
  148.       Colour -> Green = Entry->Start_Colour.Green + fraction * (Entry->End_Colour.Green - Entry->Start_Colour.Green);
  149.       Colour -> Blue = Entry->Start_Colour.Blue + fraction * (Entry->End_Colour.Blue - Entry->Start_Colour.Blue);
  150.       Colour -> Alpha = Entry->Start_Colour.Alpha + fraction * (Entry->End_Colour.Alpha - Entry->Start_Colour.Alpha);
  151.       return;
  152.       }
  153.  
  154.    Colour -> Red = 0.0;
  155.    Colour -> Green = 0.0;
  156.    Colour -> Blue = 0.0;
  157.    Colour -> Alpha = 0.0;
  158.    printf ("No colour for value: %g\n", value);
  159.    return;
  160.    }
  161.  
  162. void Initialize_Noise ()
  163.    {
  164.    register int i = 0;
  165.    VECTOR point;
  166.  
  167.    InitRTable();
  168.  
  169.    for (i = 0 ; i < SINTABSIZE ; i++)
  170.       sintab[i] = sin(i/(DBL)SINTABSIZE * (3.14159265359 * 2.0));
  171.  
  172.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++)
  173.       {
  174.       DNoise (&point, (DBL) i, 0.0, 0.0);
  175.       VNormalize (Wave_Sources[i], point);
  176.       frequency[i] = (rand() & RNDMASK) / RNDDIVISOR + 0.01;
  177.       }
  178.    }
  179.  
  180. void InitTextureTable()
  181.    {
  182.    int i, j, temp;
  183.  
  184.    srand(0);
  185.  
  186.    if ((hashTable = (short int *) malloc(4096*sizeof(short int))) == NULL) {
  187.       printf("Cannot allocate memory for hash table\n");
  188.       exit(1);
  189.       }
  190.    for (i = 0; i < 4096; i++)
  191.       hashTable[i] = i;
  192.    for (i = 4095; i >= 0; i--) {
  193.       j = rand() % 4096;
  194.       temp = hashTable[i];
  195.       hashTable[i] = hashTable[j];
  196.       hashTable[j] = temp;
  197.       }
  198.    }
  199.  
  200.  
  201. /* modified by AAC to work properly with little bitty integers (16 bits) */
  202.  
  203. void InitRTable()
  204.    {
  205.    int i;
  206.    VECTOR rp;
  207.  
  208.    InitTextureTable();
  209.  
  210.    for (i = 0; i < MAXSIZE; i++)
  211.       {
  212.       rp.x = rp.y = rp.z = (DBL)i;
  213.       RTable[i] = (unsigned int) R(&rp) * REALSCALE - 1.0;
  214.       }
  215.    }
  216.  
  217.  
  218. int R(v)
  219.    VECTOR *v;
  220.    {
  221.    v->x *= .12345;
  222.    v->y *= .12345;
  223.    v->z *= .12345;
  224.  
  225.    return (Crc16((char *) v, sizeof(VECTOR)));
  226.    }
  227.  
  228. /*
  229.  * Note that passing a VECTOR array to Crc16 and interpreting it as
  230.  * an array of chars means that machines with different floating-point
  231.  * representation schemes will evaluate Noise(point) differently.
  232.  */
  233.  
  234. int Crc16(buf, count)
  235.    register char *buf;
  236.    register int  count;
  237.    {
  238.    register unsigned short crc = 0;
  239.  
  240.    while (count--)
  241.       crc = (crc >> 8) ^ crctab[ (unsigned char) (crc ^ *buf++) ];
  242.  
  243.    return ((int) crc);
  244.    }
  245.  
  246.  
  247. /*
  248.     Robert's Skinner's Perlin-style "Noise" function - modified by AAC
  249.     to ensure uniformly distributed clamped values between 0 and 1.0...
  250. */
  251.  
  252. void setup_lattice(x, y, z, ix, iy, iz, jx, jy, jz, sx, sy, sz, tx, ty, tz)
  253.    DBL *x, *y, *z, *sx, *sy, *sz, *tx, *ty, *tz;
  254.    long *ix, *iy, *iz, *jx, *jy, *jz;
  255.    {
  256.    /* ensures the values are positive. */
  257.    *x -= MINX;
  258.    *y -= MINY;
  259.    *z -= MINZ;
  260.  
  261.    /* its equivalent integer lattice point. */
  262.    *ix = (long)*x; *iy = (long)*y; *iz = (long)*z;
  263.    *jx = *ix + 1; *jy = *iy + 1; *jz = *iz + 1;
  264.  
  265.    *sx = SCURVE(*x - *ix); *sy = SCURVE(*y - *iy); *sz = SCURVE(*z - *iz);
  266.  
  267.    /* the complement values of sx,sy,sz */
  268.    *tx = 1.0 - *sx; *ty = 1.0 - *sy; *tz = 1.0 - *sz;
  269.    return;
  270.    }
  271.  
  272.  
  273. DBL Noise(x, y, z)
  274.    DBL x, y, z;
  275.    {
  276.    long ix, iy, iz, jx, jy, jz;
  277.    DBL sx, sy, sz, tx, ty, tz;
  278.    DBL sum;
  279.    short m;
  280.  
  281.  
  282.    Calls_To_Noise++;
  283.    
  284.    setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);
  285.  
  286.    /*
  287.     *  interpolate!
  288.     */
  289.    m = Hash3d( ix, iy, iz ) & 0xFF;
  290.    sum = INCRSUM(m,(tx*ty*tz),(x-ix),(y-iy),(z-iz));
  291.  
  292.    m = Hash3d( jx, iy, iz ) & 0xFF;
  293.    sum += INCRSUM(m,(sx*ty*tz),(x-jx),(y-iy),(z-iz));
  294.  
  295.    m = Hash3d( ix, jy, iz ) & 0xFF;
  296.    sum += INCRSUM(m,(tx*sy*tz),(x-ix),(y-jy),(z-iz));
  297.  
  298.    m = Hash3d( jx, jy, iz ) & 0xFF;
  299.    sum += INCRSUM(m,(sx*sy*tz),(x-jx),(y-jy),(z-iz));
  300.  
  301.    m = Hash3d( ix, iy, jz ) & 0xFF;
  302.    sum += INCRSUM(m,(tx*ty*sz),(x-ix),(y-iy),(z-jz));
  303.  
  304.    m = Hash3d( jx, iy, jz ) & 0xFF;
  305.    sum += INCRSUM(m,(sx*ty*sz),(x-jx),(y-iy),(z-jz));
  306.  
  307.    m = Hash3d( ix, jy, jz ) & 0xFF;
  308.    sum += INCRSUM(m,(tx*sy*sz),(x-ix),(y-jy),(z-jz));
  309.  
  310.    m = Hash3d( jx, jy, jz ) & 0xFF;
  311.    sum += INCRSUM(m,(sx*sy*sz),(x-jx),(y-jy),(z-jz));
  312.  
  313.    sum = sum + 0.5;          /* range at this point -0.5 - 0.5... */
  314.     
  315.    if (sum < 0.0)
  316.       sum = 0.0;
  317.    if (sum > 1.0)
  318.       sum = 1.0;
  319.  
  320.    return (sum);
  321.    }
  322.  
  323.  
  324. /*
  325.        Vector-valued version of "Noise"
  326. */
  327.  
  328. void DNoise(result, x, y, z)
  329.    VECTOR *result;
  330.    DBL x, y, z;
  331.    {
  332.    long ix, iy, iz, jx, jy, jz;
  333.    DBL px, py, pz, s;
  334.    DBL sx, sy, sz, tx, ty, tz;
  335.    short m;
  336.  
  337.    Calls_To_DNoise++;
  338.  
  339.    setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);
  340.  
  341.    /*
  342.     *  interpolate!
  343.     */
  344.    m = Hash3d( ix, iy, iz ) & 0xFF;
  345.    px = x-ix;  py = y-iy;  pz = z-iz;
  346.    s = tx*ty*tz;
  347.    result->x = INCRSUM(m,s,px,py,pz);
  348.    result->y = INCRSUM(m+4,s,px,py,pz);
  349.    result->z = INCRSUM(m+8,s,px,py,pz);
  350.  
  351.    m = Hash3d( jx, iy, iz ) & 0xFF;
  352.    px = x-jx;
  353.    s = sx*ty*tz;
  354.    result->x += INCRSUM(m,s,px,py,pz);
  355.    result->y += INCRSUM(m+4,s,px,py,pz);
  356.    result->z += INCRSUM(m+8,s,px,py,pz);
  357.  
  358.    m = Hash3d( jx, jy, iz ) & 0xFF;
  359.    py = y-jy;
  360.    s = sx*sy*tz;
  361.    result->x += INCRSUM(m,s,px,py,pz);
  362.    result->y += INCRSUM(m+4,s,px,py,pz);
  363.    result->z += INCRSUM(m+8,s,px,py,pz);
  364.  
  365.    m = Hash3d( ix, jy, iz ) & 0xFF;
  366.    px = x-ix;
  367.    s = tx*sy*tz;
  368.    result->x += INCRSUM(m,s,px,py,pz);
  369.    result->y += INCRSUM(m+4,s,px,py,pz);
  370.    result->z += INCRSUM(m+8,s,px,py,pz);
  371.  
  372.    m = Hash3d( ix, jy, jz ) & 0xFF;
  373.    pz = z-jz;
  374.    s = tx*sy*sz;
  375.    result->x += INCRSUM(m,s,px,py,pz);
  376.    result->y += INCRSUM(m+4,s,px,py,pz);
  377.    result->z += INCRSUM(m+8,s,px,py,pz);
  378.  
  379.    m = Hash3d( jx, jy, jz ) & 0xFF;
  380.    px = x-jx;
  381.    s = sx*sy*sz;
  382.    result->x += INCRSUM(m,s,px,py,pz);
  383.    result->y += INCRSUM(m+4,s,px,py,pz);
  384.    result->z += INCRSUM(m+8,s,px,py,pz);
  385.  
  386.    m = Hash3d( jx, iy, jz ) & 0xFF;
  387.    py = y-iy;
  388.    s = sx*ty*sz;
  389.    result->x += INCRSUM(m,s,px,py,pz);
  390.    result->y += INCRSUM(m+4,s,px,py,pz);
  391.    result->z += INCRSUM(m+8,s,px,py,pz);
  392.  
  393.    m = Hash3d( ix, iy, jz ) & 0xFF;
  394.    px = x-ix;
  395.    s = tx*ty*sz;
  396.    result->x += INCRSUM(m,s,px,py,pz);
  397.    result->y += INCRSUM(m+4,s,px,py,pz);
  398.    result->z += INCRSUM(m+8,s,px,py,pz);
  399.    }
  400.  
  401. DBL Turbulence (x, y, z)
  402.    DBL x, y, z;
  403.    {
  404.    register DBL pixelSize = 0.1;
  405.    register DBL t = 0.0;
  406.    register DBL scale, value;
  407.  
  408.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  409.       value = Noise (x/scale, y/scale, z/scale);
  410.       t += FABS (value) * scale;
  411.       }
  412.    return (t);
  413.    }
  414.  
  415. void DTurbulence (result, x, y, z)
  416.    VECTOR *result;
  417.    DBL x, y, z;
  418.    {
  419.    register DBL pixelSize = 0.01;
  420.    register DBL scale;
  421.    VECTOR value;
  422.  
  423.    result -> x = 0.0;
  424.    result -> y = 0.0;
  425.    result -> z = 0.0;
  426.  
  427.    value.x = value.y = value.z = 0.0;
  428.  
  429.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  430.       DNoise(&value, x/scale, y/scale, z/scale);
  431.       result -> x += value.x * scale;
  432.       result -> y += value.y * scale;
  433.       result -> z += value.z * scale;
  434.       }
  435.    }
  436.  
  437. DBL cycloidal (value)
  438.    DBL value;
  439.    {
  440.  
  441.    if (value >= 0.0)
  442.       return (sintab [(int)((value - floor (value)) * SINTABSIZE)]);
  443.    else
  444.       return (0.0 - sintab [(int)((0.0 - (value + floor (0.0 - value)))
  445.                                     * SINTABSIZE)]);
  446.    }
  447.  
  448.  
  449. DBL Triangle_Wave (value)
  450.    DBL value;
  451.    {
  452.    register DBL offset;
  453.  
  454.    if (value >= 0.0) offset = value - floor(value);
  455.    else offset = value - (-1.0 - floor(FABS(value)));
  456.  
  457.    if (offset >= 0.5) return (2.0 * (1.0 - offset));
  458.    else return (2.0 * offset);
  459.    }
  460.  
  461.  
  462. int Bozo (x, y, z, Texture, Colour)
  463. DBL x, y, z;
  464. TEXTURE *Texture;
  465. COLOUR *Colour;
  466.    {
  467.    register DBL noise, turb;
  468.    COLOUR New_Colour;
  469.    VECTOR BozoTurbulence;
  470.  
  471.  
  472.    if (Options & DEBUGGING)
  473.       printf ("bozo %g %g %g ", x, y, z);
  474.  
  475.    if ((turb = Texture->Turbulence) != 0.0)
  476.       {
  477.       DTurbulence (&BozoTurbulence, x, y, z);
  478.       x += BozoTurbulence.x * turb;
  479.       y += BozoTurbulence.y * turb;
  480.       z += BozoTurbulence.z * turb;
  481.       }
  482.  
  483.    noise = Noise (x, y, z);
  484.  
  485.    if (Options & DEBUGGING)
  486.       printf ("noise %g\n", noise);
  487.  
  488.    if (Texture -> Colour_Map != NULL) {
  489.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  490.       Colour -> Red += New_Colour.Red;
  491.       Colour -> Green += New_Colour.Green;
  492.       Colour -> Blue += New_Colour.Blue;
  493.       Colour -> Alpha += New_Colour.Alpha;
  494.       return (0);
  495.       }
  496.  
  497.    if (noise < 0.4) {
  498.       Colour -> Red += 1.0;
  499.       Colour -> Green += 1.0;
  500.       Colour -> Blue += 1.0;
  501.       return (0);
  502.       }
  503.  
  504.    if (noise < 0.6) {
  505.       Colour -> Green += 1.0;
  506.       return (0);
  507.       }
  508.  
  509.    if (noise < 0.8) {
  510.       Colour -> Blue += 1.0;
  511.       return (0);
  512.       }
  513.  
  514.    Colour -> Red += 1.0;
  515.    return (0);
  516.    }
  517.  
  518. int marble (x, y, z, Texture, colour)
  519.    DBL x, y, z;
  520.    TEXTURE *Texture;
  521.    COLOUR *colour;
  522.    {
  523.    register DBL noise, hue;
  524.    COLOUR New_Colour;
  525.  
  526.    noise = Triangle_Wave(x + Turbulence(x, y, z) * Texture -> Turbulence);
  527.  
  528.    if (Options & DEBUGGING)
  529.       printf ("marble %g %g %g noise %g \n", x, y, z, noise);
  530.  
  531.    if (Texture -> Colour_Map != NULL)
  532.       {
  533.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  534.       colour -> Red += New_Colour.Red;
  535.       colour -> Green += New_Colour.Green;
  536.       colour -> Blue += New_Colour.Blue;
  537.       colour -> Alpha += New_Colour.Alpha;
  538.       return (0);
  539.       }
  540.  
  541.    if (noise < 0.0)
  542.       {
  543.       colour -> Red += 0.9;
  544.       colour -> Green += 0.8;
  545.       colour -> Blue += 0.8;
  546.       }
  547.    else if (noise < 0.9)
  548.       {
  549.       colour -> Red += 0.9;
  550.       hue = 0.8 - noise * 0.8;
  551.       colour -> Green += hue;
  552.       colour -> Blue += hue;
  553.       }
  554.    return (0);
  555.    }
  556.  
  557.  
  558. void ripples (x, y, z, Texture, Vector)
  559.    DBL x, y, z;
  560.    TEXTURE *Texture;
  561.    VECTOR *Vector;
  562.    {
  563.    register int i;
  564.    VECTOR point;
  565.    register DBL length, scalar, index;
  566.  
  567.    if (Options & DEBUGGING)
  568.       printf ("ripples %g %g %g", x, y, z);
  569.  
  570.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  571.       point.x = x;
  572.       point.y = y;
  573.       point.z = z;
  574.       VSub (point, point, Wave_Sources[i]);
  575.       VDot (length, point, point);
  576.       if (length == 0.0)
  577.          length = 1.0;
  578.  
  579.       length = sqrt(length);
  580.       index = length*Texture->Frequency
  581.                     + Texture -> Phase;
  582.       scalar = cycloidal (index) * Texture -> Bump_Amount;
  583.  
  584.       if (Options & DEBUGGING)
  585.          printf (" index %g scalar %g length %g\n", index, scalar, length);
  586.       
  587.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  588.       VAdd (*Vector, *Vector, point);
  589.       }
  590.    VNormalize (*Vector, *Vector);
  591.    }
  592.  
  593. void waves (x, y, z, Texture, Vector)
  594.    DBL x, y, z;
  595.    TEXTURE *Texture;
  596.    VECTOR *Vector;
  597.    {
  598.    register int i;
  599.    VECTOR point;
  600.    register DBL length, scalar, index, sinValue ;
  601.  
  602.    if (Options & DEBUGGING)
  603.       printf ("waves %g %g %g\n", x, y, z);
  604.  
  605.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  606.       point.x = x;
  607.       point.y = y;
  608.       point.z = z;
  609.       VSub (point, point, Wave_Sources[i]);
  610.       VDot (length, point, point);
  611.       if (length == 0.0)
  612.          length = 1.0;
  613.  
  614.       length = sqrt(length);
  615.       index = (length * Texture -> Frequency * frequency[i])
  616.                    + Texture -> Phase;
  617.       sinValue = cycloidal (index);
  618.  
  619.       scalar =  sinValue * Texture -> Bump_Amount /
  620.                   frequency[i];
  621.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  622.       VAdd (*Vector, *Vector, point);
  623.       }
  624.    VNormalize (*Vector, *Vector);
  625.    }
  626.  
  627. int wood (x, y, z, Texture, colour)
  628.    DBL x, y, z;
  629.    TEXTURE *Texture;
  630.    COLOUR *colour;
  631.    {
  632.    register DBL noise, length;
  633.    VECTOR WoodTurbulence;
  634.    VECTOR point;
  635.    COLOUR New_Colour;
  636.  
  637.    DTurbulence (&WoodTurbulence, x, y, z);
  638.  
  639.    if (Options & DEBUGGING)
  640.       printf ("wood %g %g %g", x, y, z);
  641.  
  642.    point.x = cycloidal((x + WoodTurbulence.x)
  643.                * Texture -> Turbulence);
  644.    point.y = cycloidal((y + WoodTurbulence.y)
  645.                * Texture -> Turbulence);
  646.    point.z = 0.0;
  647.  
  648.    point.x += x;
  649.    point.y += y;
  650.    point.z += z;
  651.  
  652.    VLength (length, point);
  653.  
  654.    noise = Triangle_Wave(length);
  655.  
  656.    if (Options & DEBUGGING)
  657.       printf ("noise %g\n", noise);
  658.  
  659.    if (Texture -> Colour_Map != NULL) {
  660.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  661.       colour -> Red += New_Colour.Red;
  662.       colour -> Green += New_Colour.Green;
  663.       colour -> Blue += New_Colour.Blue;
  664.       colour -> Alpha += New_Colour.Alpha;
  665.       return (0);
  666.       }
  667.  
  668.    if (noise > 0.6) {
  669.       colour -> Red += 0.4;
  670.       colour -> Green += 0.133;
  671.       colour -> Blue += 0.066;
  672.       }
  673.   else {
  674.       colour -> Red += 0.666;
  675.       colour -> Green += 0.312;
  676.       colour -> Blue += 0.2;
  677.       }
  678.       return (0);
  679.    }
  680.  
  681.  
  682. void checker (x, y, z, Texture, colour)
  683.    DBL x, y, z;
  684.    TEXTURE *Texture;
  685.    COLOUR *colour;
  686.    {
  687.    int brkindx;
  688.  
  689.    brkindx = (int) FLOOR(x) + (int) FLOOR(z);
  690.  
  691.    if (Options & DEBUGGING)
  692.       printf ("checker %g %g %g\n", x, y, z);
  693.  
  694.    if (brkindx & 1)
  695.       *colour = *Texture -> Colour1;
  696.    else
  697.       *colour = *Texture -> Colour2;
  698.    return;
  699.    }
  700.  
  701.  
  702.  
  703. void checker_texture (x, y, z, Texture, colour)
  704.    DBL x, y, z;
  705.    TEXTURE *Texture;
  706.    COLOUR *colour;
  707.    {
  708.    int brkindx;
  709.    VECTOR Point;
  710.  
  711.    brkindx = (int) FLOOR(x) + (int) FLOOR(z);
  712.  
  713.    if (Options & DEBUGGING)
  714.       printf ("checker_texture %g %g %g\n", x, y, z);
  715.  
  716.    Make_Vector (&Point, x, y, z);
  717.  
  718.    if (brkindx & 1)
  719.       Colour_At (colour, ((TEXTURE *) Texture -> Colour1), &Point);
  720.    else
  721.       Colour_At (colour, ((TEXTURE *) Texture -> Colour2), &Point);
  722.    return;
  723.    }
  724.  
  725.  
  726.  
  727. /*
  728.    Ideas garnered from SIGGRAPH '85 Volume 19 Number 3, "An Image Synthesizer"
  729.    By Ken Perlin.
  730. */
  731.  
  732.  
  733. /*    
  734.     With a little reflectivity and brilliance, can look like organ pipe
  735.     metal.   With tiny scaling values can look like masonry or concrete.
  736.     Works with color maps, supposedly. (?)
  737. */
  738.  
  739. void spotted (x, y, z, Texture, Colour)
  740.    DBL x, y, z;
  741.    TEXTURE *Texture;
  742.    COLOUR *Colour;
  743.    {
  744.    register DBL noise;
  745.    COLOUR New_Colour;
  746.  
  747.    noise = Noise (x, y, z);
  748.  
  749.    if (Options & DEBUGGING)
  750.       printf ("spotted %g %g %g\n", x, y, z);
  751.  
  752.    if (Texture -> Colour_Map != NULL)
  753.       {
  754.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  755.       Colour -> Red += New_Colour.Red;
  756.       Colour -> Green += New_Colour.Green;
  757.       Colour -> Blue += New_Colour.Blue;
  758.       Colour -> Alpha += New_Colour.Alpha;
  759.       return;
  760.       }
  761.  
  762.    Colour -> Red += noise;             /* "white (1.0) * noise" */
  763.    Colour -> Green += noise;
  764.    Colour -> Blue += noise;
  765.  
  766.    return;
  767.    }
  768.  
  769. void bumps (x, y, z, Texture, normal)
  770.    DBL x, y, z;
  771.    TEXTURE *Texture;
  772.    VECTOR *normal;
  773.    {
  774.    VECTOR bump_turb;
  775.  
  776.    if (Texture -> Bump_Amount == 0.0)
  777.       return;                            /* why are we here?? */
  778.  
  779.    if (Options & DEBUGGING)
  780.       printf ("bumps %g %g %g\n", x, y, z);
  781.  
  782.    DNoise (&bump_turb, x, y, z);         /* Get Normal Displacement Val. */
  783.    VScale(bump_turb, bump_turb, Texture->Bump_Amount);
  784.    VAdd (*normal, *normal, bump_turb);   /* displace "normal" */
  785.    VNormalize (*normal, *normal);        /* normalize normal! */
  786.    return;
  787.    }
  788.  
  789. /*
  790.    dents is similar to bumps, but uses noise() to control the amount of
  791.    dnoise() perturbation of the object normal...
  792. */
  793.  
  794. void dents (x, y, z, Texture, normal)
  795.    DBL x, y, z;
  796.    TEXTURE *Texture;
  797.    VECTOR *normal;
  798.    {
  799.    VECTOR stucco_turb;
  800.    DBL noise;
  801.  
  802.    if (Texture -> Bump_Amount == 0.0)
  803.       return;                           /* why are we here?? */
  804.  
  805.    noise = Noise (x, y, z);
  806.  
  807.    noise =  noise * noise * noise * Texture->Bump_Amount;
  808.  
  809.    if (Options & DEBUGGING)
  810.       printf ("dents %g %g %g noise %g\n", x, y, z, noise);
  811.  
  812.    DNoise (&stucco_turb, x, y, z);       /* Get Normal Displacement Val. */
  813.     
  814.    VScale (stucco_turb, stucco_turb, noise);
  815.    VAdd (*normal, *normal, stucco_turb); /* displace "normal" */
  816.    VNormalize (*normal, *normal);        /* normalize normal! */
  817.    return;
  818.    }
  819.  
  820.  
  821. void agate (x, y, z, Texture, colour)
  822.    DBL x, y, z;
  823.    TEXTURE *Texture;
  824.    COLOUR *colour;
  825.    {
  826.    register DBL noise, hue;
  827.    COLOUR New_Colour;
  828.  
  829.    noise = cycloidal(1.3 * Turbulence(x, y, z) + 1.1 * z) + 1;
  830.    noise *= 0.5;
  831.    noise = pow(noise, 0.77);
  832.  
  833.    if (Options & DEBUGGING)
  834.       printf ("agate %g %g %g noise %g\n", x, y, z, noise);
  835.  
  836.    if (Texture -> Colour_Map != NULL)
  837.       {
  838.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  839.       colour -> Red += New_Colour.Red;
  840.       colour -> Green += New_Colour.Green;
  841.       colour -> Blue += New_Colour.Blue;
  842.       colour -> Alpha += New_Colour.Alpha;
  843.       return;
  844.       }
  845.  
  846.    hue = 1.0 - noise;
  847.  
  848.    if (noise < 0.5)
  849.       {
  850.       colour -> Red += (1.0 - (noise / 10));
  851.       colour -> Green += (1.0 - (noise / 5));
  852.       colour -> Blue += hue;
  853.       }
  854.    else if (noise < 0.6)
  855.       {
  856.       colour -> Red += 0.9;
  857.       colour -> Green += 0.7;
  858.       colour -> Blue += hue;
  859.       }
  860.    else
  861.       {
  862.       colour -> Red += (0.6 + hue);
  863.       colour -> Green += (0.3 + hue);
  864.       colour -> Blue += hue;
  865.       }
  866.    return;
  867.    }
  868.  
  869.  
  870. /*
  871.    Ideas garnered from the April 89 Byte Graphics Supplement on RenderMan,
  872.    refined from "The RenderMan Companion, by Steve Upstill of Pixar, (C) 1990
  873.    Addison-Wesley.
  874. */
  875.  
  876.  
  877. /*
  878.    wrinkles - This is my implementation of the dented() routine, using
  879.    a surface iterative fractal derived from DTurbulence.  This is a 3-D vers.
  880.    (thanks to DNoise()...) of the usual version using the singular Noise()...
  881.    Seems to look a lot like wrinkles, however... (hmmm)
  882. */
  883.  
  884. void wrinkles (x, y, z, Texture, normal)
  885.    DBL x, y, z;
  886.    TEXTURE *Texture;
  887.    VECTOR *normal;
  888.    {
  889.    register int i;
  890.    register DBL scale = 1.0;
  891.    VECTOR result, value;
  892.  
  893.    if (Texture -> Bump_Amount == 0.0)
  894.       return;                                /* why are we here?? */
  895.  
  896.    if (Options & DEBUGGING)
  897.       printf ("wrinkles %g %g %g\n", x, y, z);
  898.  
  899.    result.x = 0.0;
  900.    result.y = 0.0;
  901.    result.z = 0.0;
  902.  
  903.    for (i = 0; i < 10 ; scale *= 2.0, i++)
  904.       {
  905.       DNoise(&value, x * scale, y * scale, z * scale);   /* * scale,*/
  906.       result.x += FABS (value.x / scale);
  907.       result.y += FABS (value.y / scale);
  908.       result.z += FABS (value.z / scale);
  909.       }
  910.  
  911.    VScale(result, result, Texture->Bump_Amount);
  912.    VAdd (*normal, *normal, result);             /* displace "normal" */
  913.    VNormalize (*normal, *normal);               /* normalize normal! */
  914.    return;
  915.    }
  916.  
  917.  
  918. /*
  919.    Granite - kind of a union of the "spotted" and the "dented" textures,
  920.    using a 1/f fractal noise function for color values.  Typically used
  921.    w/ small scaling values.  Should work with colour maps for pink granite...
  922. */
  923.  
  924.  
  925. void granite (x, y, z, Texture, Colour)
  926.    DBL x, y, z;
  927.    TEXTURE *Texture;
  928.    COLOUR *Colour;
  929.    {
  930.    register int i;
  931.    register DBL temp, noise = 0.0, freq = 1.0;
  932.    COLOUR New_Colour;
  933.  
  934.    for (i = 0; i < 6 ; freq *= 2.0, i++)
  935.       {
  936.       temp = 0.5 - Noise (x * 4 * freq, y * 4 * freq, z * 4 * freq);
  937.       temp = FABS(temp);
  938.       noise += temp / freq;
  939.       }
  940.  
  941.    if (Options & DEBUGGING)
  942.       printf ("granite %g %g %g noise %g\n", x, y, z, noise);
  943.  
  944.    if (Texture -> Colour_Map != NULL)
  945.       {
  946.       Compute_Colour (&New_Colour, Texture->Colour_Map, noise);
  947.       Colour -> Red += New_Colour.Red;
  948.       Colour -> Green += New_Colour.Green;
  949.       Colour -> Blue += New_Colour.Blue;
  950.       Colour -> Alpha += New_Colour.Alpha;
  951.       return;
  952.       }
  953.  
  954.    Colour -> Red += noise;                  /* "white (1.0) * noise" */
  955.    Colour -> Green += noise;
  956.    Colour -> Blue += noise;
  957.  
  958.    return;
  959.    }
  960.  
  961. /*
  962.    Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley)
  963. */
  964.  
  965.  
  966. /*
  967.    Color Gradient Texture - gradient based on the fractional values of x, y or
  968.    z, based on whether or not the given directional vector is a 1.0 or a 0.0.
  969.    Note - ONLY works with colour maps, preferably one that is circular - i.e.
  970.    the last defined colour (value 1.001) is the same as the first colour (with
  971.    a value of 0.0) in the map.  The basic concept of this is from DBW Render,
  972.    but Dave Wecker's only supports simple Y axis gradients.
  973. */
  974.  
  975. void gradient (x, y, z, Texture, Colour)
  976.    DBL x, y, z;
  977.    TEXTURE *Texture;
  978.    COLOUR *Colour;
  979.    {
  980.    COLOUR New_Colour;
  981.    DBL value = 0.0, turb;
  982.    VECTOR GradTurbulence;
  983.  
  984.    if ((turb = Texture->Turbulence) != 0.0)
  985.       {
  986.       DTurbulence (&GradTurbulence, x, y, z);
  987.       x += GradTurbulence.x * turb;
  988.       y += GradTurbulence.y * turb;
  989.       z += GradTurbulence.z * turb;
  990.       }
  991.  
  992.    if (Texture -> Colour_Map == NULL)
  993.       return;
  994.    if (Texture -> Texture_Gradient.x != 0.0)
  995.       {
  996.       x = FABS(x);
  997.       value += x - FLOOR(x);    /* obtain fractional X component */
  998.       }
  999.    if (Texture -> Texture_Gradient.y != 0.0)
  1000.       {
  1001.       y = FABS(y);
  1002.       value += y - FLOOR(y);    /* obtain fractional Y component */
  1003.    }
  1004.    if (Texture -> Texture_Gradient.z != 0.0)
  1005.       {
  1006.       z = FABS(z);
  1007.       value += z - FLOOR(z);    /* obtain fractional Z component */
  1008.       }
  1009.    value = ((value > 1.0) ? fmod(value, 1.0) : value); /* clamp to 1.0 */
  1010.  
  1011.    if (Options & DEBUGGING)
  1012.       printf ("gradient %g %g %g value %g\n", x, y, z, value);
  1013.  
  1014.    Compute_Colour(&New_Colour, Texture->Colour_Map, value);
  1015.    Colour -> Red += New_Colour.Red;
  1016.    Colour -> Green += New_Colour.Green;
  1017.    Colour -> Blue += New_Colour.Blue;
  1018.    Colour -> Alpha += New_Colour.Alpha;
  1019.    return;
  1020.    }
  1021.  
  1022. /*
  1023.    2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  1024.        
  1025.    Simplistic method of object image projection devised by DKB and AAC.
  1026.  
  1027.    1. Transform texture in 3-D space if requested.
  1028.    2. Determine local object 2-d coords from 3-d coords by <X Y Z> triple.
  1029.    3. Return pixel color value at that position on the 2-d plane of "Image".
  1030.    3. Map colour value in Image [0..255] to a more normal colour range [0..1].
  1031. */
  1032.  
  1033. void texture_map (x, y, z, Texture, colour)
  1034.    DBL x, y, z;
  1035.    TEXTURE *Texture;
  1036.    COLOUR *colour;
  1037.    {
  1038.    /* determine local object 2-d coords from 3-d coords */
  1039.    /* "unwrap" object 2-d coord onto flat 2-d plane */
  1040.    /* return pixel color value at that posn on 2-d plane */
  1041.  
  1042.    int xcoor = 0, ycoor = 0;
  1043.    DBL width, height, turb;
  1044.    VECTOR TextureTurbulence;
  1045.    struct Image_Line *line;
  1046.    int reg_number;
  1047.    IMAGE_COLOUR *reg_colour;
  1048.  
  1049.    if ((turb = Texture->Turbulence) != 0.0)
  1050.       {
  1051.       DTurbulence (&TextureTurbulence, x, y, z);
  1052.       x += TextureTurbulence.x * turb;
  1053.       y += TextureTurbulence.y * turb;
  1054.       z += TextureTurbulence.z * turb;
  1055.       }
  1056.  
  1057.    width = Texture->Image->width;
  1058.    height = Texture->Image->height;
  1059.  
  1060.    if (Texture -> Texture_Gradient.x != 0.0) {
  1061.       if ((Texture->Once_Flag) &&
  1062.            ((x < 0.0) || (x > 1.0))) {
  1063.  
  1064.          Make_Colour (colour, 1.0, 1.0, 1.0);
  1065.          colour->Alpha = 1.0;
  1066.          return;
  1067.          }
  1068.  
  1069.       if (Texture -> Texture_Gradient.x > 0)
  1070.          xcoor = (int) fmod (x * width, width);
  1071.       else ycoor = (int) fmod (x * height, height);
  1072.       }
  1073.  
  1074.    if (Texture -> Texture_Gradient.y != 0.0) {
  1075.       if ((Texture->Once_Flag) &&
  1076.            ((y < 0.0) || (y > 1.0))) {
  1077.  
  1078.          Make_Colour (colour, 1.0, 1.0, 1.0);
  1079.          colour->Alpha = 1.0;
  1080.          return;
  1081.          }
  1082.  
  1083.       if (Texture -> Texture_Gradient.y > 0)
  1084.          xcoor = (int) fmod (y * width, width);
  1085.       else ycoor = (int) fmod (y * height, height);
  1086.       }
  1087.  
  1088.    if (Texture -> Texture_Gradient.z != 0.0) {
  1089.       if ((Texture->Once_Flag) &&
  1090.            ((z < 0.0) || (z > 1.0))) {
  1091.          Make_Colour (colour, 1.0, 1.0, 1.0);
  1092.          colour->Alpha = 1.0;
  1093.          return;
  1094.          }
  1095.  
  1096.       if (Texture -> Texture_Gradient.z > 0)
  1097.          xcoor = (int) fmod (z * width, width);
  1098.       else ycoor = (int) fmod (z * height, height);
  1099.       }
  1100.  
  1101.    /* Compensate for y coordinates on the images being upsidedown */
  1102.    ycoor = Texture->Image->iheight - ycoor;
  1103.  
  1104.    if (xcoor < 0)
  1105.       xcoor += Texture->Image->iwidth;
  1106.    else if (xcoor >= Texture->Image->iwidth)
  1107.       xcoor -= Texture->Image->iwidth;
  1108.  
  1109.    if (ycoor < 0)
  1110.       ycoor += Texture->Image->iheight;
  1111.    else if (ycoor >= Texture->Image->iheight)
  1112.       ycoor -= Texture->Image->iheight;
  1113.  
  1114.    if ((xcoor >= Texture->Image->iwidth) ||
  1115.        (ycoor >= Texture->Image->iheight) ||
  1116.        (xcoor < 0) || (ycoor < 0)) {
  1117.      printf ("Picture index out of range\n");
  1118.      close_all();
  1119.      exit (1);
  1120.      }
  1121.  
  1122.    if (Options & DEBUGGING)
  1123.       printf ("texture %g %g %g xcoor %d ycoor %d\n", x, y, z, xcoor, ycoor);
  1124.  
  1125.    if (Texture->Image->Colour_Map == NULL) {
  1126.       line = &Texture->Image->data.rgb_lines[ycoor];
  1127.       colour -> Red += (DBL) line->red[xcoor]/255.0;
  1128.       colour -> Green += (DBL) line->green[xcoor]/255.0;
  1129.       colour -> Blue += (DBL) line->blue[xcoor]/255.0;
  1130.       }
  1131.    else {
  1132.       reg_number = Texture->Image->data.map_lines[ycoor][xcoor];
  1133.       reg_colour = &Texture->Image->Colour_Map[reg_number];
  1134.  
  1135.       colour -> Red   += (DBL) reg_colour->Red/255.0;
  1136.       colour -> Green += (DBL) reg_colour->Green/255.0;
  1137.       colour -> Blue  += (DBL) reg_colour->Blue/255.0;
  1138.       colour -> Alpha += (DBL) reg_colour->Alpha/255.0;
  1139.       }
  1140.    }
  1141.  
  1142.  
  1143. void Translate_Texture (Texture_Ptr, Vector)
  1144.    TEXTURE **Texture_Ptr;
  1145.    VECTOR *Vector;
  1146.    {
  1147.    TEXTURE *Texture = *Texture_Ptr;
  1148.    TRANSFORMATION Transformation;
  1149.  
  1150.    while (Texture != NULL) {
  1151.       if (((Texture->Texture_Number != NO_TEXTURE)
  1152.             && (Texture->Texture_Number != COLOUR_TEXTURE))
  1153.          || (Texture->Bump_Number != NO_BUMPS)) {
  1154.       
  1155.          if (Texture->Constant_Flag) {
  1156.             Texture = Copy_Texture (Texture);
  1157.             *Texture_Ptr = Texture;
  1158.             Texture->Constant_Flag = FALSE;
  1159.             }
  1160.  
  1161.          if (!Texture -> Texture_Transformation)
  1162.             Texture -> Texture_Transformation = Get_Transformation ();
  1163.          Get_Translation_Transformation (&Transformation,
  1164.                                      Vector);
  1165.          Compose_Transformations (Texture -> Texture_Transformation,
  1166.                                   &Transformation);
  1167.          if (Texture->Texture_Number == CHECKER_TEXTURE_TEXTURE) {
  1168.             Translate_Texture ((TEXTURE **) &Texture->Colour1, Vector);
  1169.             Translate_Texture ((TEXTURE **) &Texture->Colour2, Vector);
  1170.             }
  1171.          }
  1172.       Texture_Ptr = &Texture->Next_Texture;
  1173.       Texture = Texture->Next_Texture;
  1174.       }
  1175.    }
  1176.  
  1177. void Rotate_Texture (Texture_Ptr, Vector)
  1178.    TEXTURE **Texture_Ptr;
  1179.    VECTOR *Vector;
  1180.    {
  1181.    TEXTURE *Texture = *Texture_Ptr;
  1182.    TRANSFORMATION Transformation;
  1183.  
  1184.    while (Texture != NULL) {
  1185.       if (((Texture->Texture_Number != NO_TEXTURE)
  1186.             && (Texture->Texture_Number != COLOUR_TEXTURE))
  1187.          || (Texture->Bump_Number != NO_BUMPS)) {
  1188.       
  1189.          if (Texture->Constant_Flag) {
  1190.             Texture = Copy_Texture (Texture);
  1191.             *Texture_Ptr = Texture;
  1192.             Texture->Constant_Flag = FALSE;
  1193.             }
  1194.  
  1195.          if (!Texture -> Texture_Transformation)
  1196.             Texture -> Texture_Transformation = Get_Transformation ();
  1197.          Get_Rotation_Transformation (&Transformation,
  1198.                                      Vector);
  1199.          Compose_Transformations (Texture -> Texture_Transformation,
  1200.                                   &Transformation);
  1201.          if (Texture->Texture_Number == CHECKER_TEXTURE_TEXTURE) {
  1202.             Rotate_Texture ((TEXTURE **) &Texture->Colour1, Vector);
  1203.             Rotate_Texture ((TEXTURE **) &Texture->Colour2, Vector);
  1204.             }
  1205.          }
  1206.       Texture_Ptr = &Texture->Next_Texture;
  1207.       Texture = Texture->Next_Texture;
  1208.       }
  1209.    }
  1210.  
  1211. void Scale_Texture (Texture_Ptr, Vector)
  1212.    TEXTURE **Texture_Ptr;
  1213.    VECTOR *Vector;
  1214.    {
  1215.    TEXTURE *Texture = *Texture_Ptr;
  1216.    TRANSFORMATION Transformation;
  1217.  
  1218.    while (Texture != NULL) {
  1219.       if (((Texture->Texture_Number != NO_TEXTURE)
  1220.             && (Texture->Texture_Number != COLOUR_TEXTURE))
  1221.          || (Texture->Bump_Number != NO_BUMPS)) {
  1222.       
  1223.          if (Texture->Constant_Flag) {
  1224.             Texture = Copy_Texture (Texture);
  1225.             *Texture_Ptr = Texture;
  1226.             Texture->Constant_Flag = FALSE;
  1227.             }
  1228.  
  1229.          if (!Texture -> Texture_Transformation)
  1230.             Texture -> Texture_Transformation = Get_Transformation ();
  1231.          Get_Scaling_Transformation (&Transformation,
  1232.                                      Vector);
  1233.          Compose_Transformations (Texture -> Texture_Transformation,
  1234.                                   &Transformation);
  1235.  
  1236.          if (Texture->Texture_Number == CHECKER_TEXTURE_TEXTURE) {
  1237.             Scale_Texture ((TEXTURE **) &Texture->Colour1, Vector);
  1238.             Scale_Texture ((TEXTURE **) &Texture->Colour2, Vector);
  1239.             }
  1240.          }
  1241.       Texture_Ptr = &Texture->Next_Texture;
  1242.       Texture = Texture->Next_Texture;
  1243.       }
  1244.    }
  1245.  
  1246.